package cn.demoncat.util.lang;

import cn.demoncat.util.exception.ParamRuntimeException;
import cn.demoncat.util.lang.constant.StringConstant;
import cn.demoncat.util.lang.entity.MapSo;
import cn.demoncat.util.lang.entity.MapSs;
import cn.demoncat.util.lang.fn.Function2;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.Map.Entry;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * Map工具
 * 
 * @author 延晓磊
 *
 * @since 2018年5月17日
 */
public class MapUtil {

	/**
	 * 判断是否为Map
	 * 
	 * @param o
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年10月10日
	 */
	public static boolean isMap(Object o) {
		return o instanceof Map;
	}
	
	/**
	 * 判断是否为Map
	 * 
	 * @param clazz
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年10月10日
	 */
	public static boolean isMap(Class<?> clazz) {
		return ReflectClassUtil.isSupper(Map.class, clazz);
	}
	
	/**
	 * 判断Map是否非空
	 * 
	 * @param map
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2016年6月10日
	 */
	public static boolean isNotEmpty(Map<?, ?> map) {
		return map != null && !map.isEmpty();
	}

	/**
	 * 判断Map是否为空
	 * 
	 * @param map
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2016年6月10日
	 */
	public static boolean isEmpty(Map<?, ?> map) {
		return map == null || map.isEmpty();
	}
	
	/**
	 * 添加
	 * 
	 * @param map	源Map
	 * @param key
	 * @param value
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年10月12日
	 */
	public static <K,V>void put(Map<K,V> map, K key, V value) {
		if (map == null) {
			map = new HashMap<>();
		}
		if (key != null) {
			map.put(key, value);
		}
	}
	
	/**
	 * 添加
	 * 
	 * @param map	源Map
	 * @param param	参数Map
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年10月12日
	 */
	public static <K,V>void put(Map<K,V> map, Map<K,V> param) {
		if (map == null) {
			map = new HashMap<>();
		}
		if (isNotEmpty(param)) {
			map.putAll(param);
		}
	}
	
	/**
	 * 获取值
	 * 
	 * @param map	源Map
	 * @param key
	 * 
	 * @return value
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年10月12日
	 */
	public static <K,V>V get(Map<K,V> map, K key) {
		if (map != null && key != null) {
			return map.get(key);
		}
		return null;
	}

	/**
	 * 获取值
	 *
	 * @param map
	 * @param key
	 * @param def	默认值
	 * @return
	 */
	public static <K,V>V get(Map<K,V> map, K key, V def) {
		if (map != null && key != null) {
			return map.computeIfAbsent(key, k -> def);
		}
		return null;
	}

	/**
	 * 随意获取1条数据
	 *
	 * @param map
	 * @return key
	 *
	 * @author 延晓磊
	 * @since 2022年07月29日
	 */
	public static <K>K anyKey(Map<K,?> map){
		if (MapUtils.isNotEmpty(map)) {
			for (K k : map.keySet()) {
				return k;
			}
		}
		return null;
	}

	/**
	 * 随意获取1条数据
	 *
	 * @param map
	 * @return value
	 *
	 * @author 延晓磊
	 * @since 2022年07月29日
	 */
	public static <V>V anyValue(Map<?,V> map){
		if (MapUtils.isNotEmpty(map)) {
			for (V value : map.values()) {
				return value;
			}
		}
		return null;
	}

	/**
	 * 获取Map
	 * 
	 * @param keys		键列表
	 * @param values	值列表，元素数量等于keys
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年11月21日
	 */
	public static <K,V>Map<K, V> getMap(K[] keys, V[] values) {
		Map<K, V> map = new HashMap<>();
		if (keys != null && keys.length > 0) {
			if (values == null || values.length != keys.length) {
				throw new ParamRuntimeException("键数组的元素数量必须同于值数组的元素数量");
			}
			for (int i = 0; i < keys.length; i++) {
				map.put(keys[i], values[i]);
			}
		}
		return map;
	}
	
	/**
	 * 获取Map<String, String>
	 * 
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年8月31日
	 */
	public static MapSs getSsMap() {
		return new MapSs();
	}
	
	/**
	 * 获取Map<String, Object>
	 * 
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年8月31日
	 */
	public static MapSo getSoMap() {
		return new MapSo();
	}
	
	/**
	 * 转换Map<String, Object>为Map<String, String>
	 * 
	 * @param map
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年5月17日
	 */
	public static <V>Map<String, String> toStrVal(Map<String, V> map){
		Map<String, String> map2 = new HashMap<>(map.size());
		for (Entry<String, V> entry : map.entrySet()) {
			map2.put(entry.getKey(), StringUtil.toEmptyString(entry.getValue()));
		}
		return map2;
	}

	/**
	 * 转换Map<String, Object>为Map<String, String>
	 *
	 * @param map
	 * @return
	 *
	 * @author 延晓磊
	 *
	 * @since 2018年5月17日
	 */
	public static <V>Map<String, String> toLinkedStrVal(Map<String, V> map){
		Map<String, String> map2 = new LinkedHashMap<>(map.size());
		for (Entry<String, V> entry : map.entrySet()) {
			map2.put(entry.getKey(), StringUtil.toEmptyString(entry.getValue()));
		}
		return map2;
	}

	/**
	 * 转换Map<Object, Object>为Map<String, Object>
	 *
	 * 场景：前端不能接收key为数值的map
	 *
	 * @param map
	 * @return
	 *
	 * @author 延晓磊
	 *
	 * @since 2018年5月17日
	 */
	public static <K,V>Map<String, V> toStrKey(Map<K, V> map){
		Map<String, V> map2 = new HashMap<>(map.size());
		for (Entry<K, V> entry : map.entrySet()) {
			map2.put(StringUtil.toEmptyString(entry.getKey()), entry.getValue());
		}
		return map2;
	}

	/**
	 * 转换Map<Object, Object>为Map<String, Object>
	 *
	 * 场景：前端不能接收key为数值的map
	 *
	 * @param map
	 * @return
	 *
	 * @author 延晓磊
	 *
	 * @since 2018年5月17日
	 */
	public static <K,V>Map<String, V> toLinkedStrKey(Map<K, V> map){
		Map<String, V> map2 = new LinkedHashMap<>(map.size());
		for (Entry<K, V> entry : map.entrySet()) {
			map2.put(StringUtil.toEmptyString(entry.getKey()), entry.getValue());
		}
		return map2;
	}

	/**
	 * 获取Map值
	 * 
	 * @param map
	 * @param key
	 * 
	 * @return	如果为null，返回""；如果非null，返回String
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年12月12日
	 */
	public static String getStrVal(Map<String, Object> map, String key) {
		if (map == null || key == null) {
			return StringConstant.EMPTY;
		}
		return StringUtil.toEmptyString(map.get(key));
	}
	
	/**
	 * 获取并移除Map值
	 * 
	 * @param map
	 * @param key
	 * 
	 * @return	如果为null，返回""；如果非null，返回String
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年12月12日
	 */
	public static String removeStrVal(Map<String, Object> map, String key) {
		if (map == null || key == null) {
			return StringConstant.EMPTY;
		}
		return StringUtil.toEmptyString(map.remove(key));
	}
	
	/**
	 * 添加元素到Set值
	 * 
	 * @param map
	 * @param key
	 * @param val	添加到Set的元素
	 * 
	 * @return 新值
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年3月4日
	 */
	public static <K, V>Set<V> putSet(Map<K, Set<V>> map, K key, V val) {
		if (map == null) {
			map = new HashMap<>();
		}
		// 计算put
		return map.compute(key, (k,v) ->{
			// 键不存在/值为null
			if (v == null) {
				// 返回值为null则remove；返回值非null则put
				return CollectionUtil.toSet(val);
			}else {
				// put(key, newVal)
				v.add(val);
				return v;
			}
		});
	}
	
	/**
	 * 移除元素从Set值
	 * 
	 * @param map
	 * @param key
	 * @param val	从Set移除的元素
	 * 
	 * @return 新值
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年3月4日
	 */
	public static <K, V>Set<V> removeSet(Map<K, Set<V>> map, K key, V val) {
		if (map == null) {
			map = new HashMap<>();
		}
		// 计算put
		return map.compute(key, (k,v) ->{
			// 键不存在/值为null
			if (v == null || v.isEmpty()) {
				// 返回值为null，删除Key
				return null;
			}else {
				v.remove(val);
				if (v.isEmpty()) {
					// remove(key)
					return null;
				}
				// put(key, newVal)
				return v;
			}
		});
	}
	
	/**
	 * 批量删除Map元素
	 * 
	 * @param map		Map
	 * @param condition	删除条件
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年7月28日
	 */
	public static <K,V>Map<K,V> remove(Map<K,V> map, Predicate<Entry<K,V>> condition) {
		if (map == null || map.isEmpty()) {
			return map;
		}
		// 遍历，条件删除
		map.entrySet().removeIf(condition);
		return map;
	}

	/**
	 * 拼接为URL参数
	 * 
	 * @param map	k=v
	 * @return k1=v1&k2=v2
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年3月26日
	 */
	public static String toUrl(Map<String, String> map) {
		// 非空
		if (map == null || map.isEmpty()) {
			return StringConstant.EMPTY;
		}
		// 遍历拼接
		StringBuilder sd = new StringBuilder();
		for (Map.Entry<String, String> entry : map.entrySet()) {
			// &k=v
			sd.append(StringConstant.PARAM_SEPARATOR).append(entry.getKey()).append(StringConstant.EQUAL).append(entry.getValue());
		}
		return sd.substring(1);
	}
	
	/**
	 * 拼接为URL参数 - 有序
	 * 
	 * @param map	k=v
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年3月26日
	 */
	public static String toSortUrl(Map<String, String> map) {
		// 非空
		if (map == null || map.isEmpty()) {
			return StringConstant.EMPTY;
		}
		// 遍历拼接
		List<String> list = new ArrayList<>();
		for (Map.Entry<String, String> entry : map.entrySet()) {
				// k=v
				list.add(entry.getKey() + StringConstant.EQUAL + entry.getValue());
		}
		// 排序
		Collections.sort(list);
		// 拼接List元素，以&分隔
		return StringUtils.join(list, StringConstant.PARAM_SEPARATOR);
	}
	
	/**
	 * 清除Null元素
	 * 
	 * @param map
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年3月26日
	 */
	public static Map<String, Object> clearNull(Map<String, Object> map){
		// 通过Iterator删除Entry
		Iterator<Entry<String, Object>> iterator = map.entrySet().iterator();
		Entry<String, Object> entry;
		while(iterator.hasNext()) {
			entry = iterator.next();
			if (null == entry.getValue()) {
				iterator.remove();
			}
		}
		return map;
	}
	
	/**
	 * 清除null元素
	 * 
	 * @param map
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年3月26日
	 */
	public static Map<String, String> clearNull2(Map<String, String> map){
		// 通过Iterator删除Entry
		Iterator<Entry<String, String>> iterator = map.entrySet().iterator();
		Entry<String, String> entry;
		while(iterator.hasNext()) {
			entry = iterator.next();
			if (StringUtil.isNull(entry.getValue())) {
				iterator.remove();
			}
		}
		return map;
	}
	
	/**
	 * 清除空元素
	 * 
	 * @param map
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年3月26日
	 */
	public static Map<String, String> clearEmpty(Map<String, String> map){
		// 通过Iterator删除Entry
		Iterator<Entry<String, String>> iterator = map.entrySet().iterator();
		Entry<String, String> entry;
		while(iterator.hasNext()) {
			entry = iterator.next();
			if (StringUtil.isBlank(entry.getValue())) {
				iterator.remove();
			}
		}
		return map;
	}
	
	/**
	 * 转换为Object
	 * 
	 * @param map
	 * @param clazz
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年4月18日
	 */
	public static <T>T toObj(Map<String, ?> map, Class<T> clazz) {
		return ReflectUtil.toObj(map, clazz);
	}
	
	/**
	 * 转换为Object
	 * 
	 * @param map				数据源（排除null字段，保留类的初始字段）
	 * @param clazz				对象类型
	 * @param excludeNull		是否排除数据源的null值：true Map值为null时忽略
	 * @param excludeNotNull	是否排除目标对象的非null值：true 目标对象的字段非null时忽略
	 * 
	 * @return obj	赋值实例字段：包含继承字段，不包含final字段
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年9月25日
	 */
	public static <T>T toObj(Map<String, ?> map, Class<T> clazz, boolean excludeNull, boolean excludeNotNull) {
		return ReflectUtil.toObj(map, clazz, excludeNull, excludeNotNull);
	}
	
	/**
	 * 设置Map.V
	 * 
	 * @param map
	 * @param key	存在则修改，不存在/值为null则忽略
	 * @param val	新V
	 * 
	 * @return val修改成功；null不存在
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年5月20日
	 */
	public static <K, V>V set(Map<K, V> map, K key, V val){
		return map.compute(key, (k,v) -> v == null ? null : val);
	}
	
	/**
	 * 设置Map.V
	 * 
	 * @param map
	 * @param key	存在则put(key,fn(v,val))，不存在则put(key,val)
	 * @param val	新V
	 * @param fn	修改器（旧V,新V）
	 * 
	 * @return K存在为fn(v,val)，不存在为val
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年5月20日
	 */
	public static <K, V>V set(Map<K, V> map, K key, V val, Function2<V,V,V> fn){
		return map.compute(key, (k,v) -> v == null ? val : fn.apply(v,val));
	}

	/**
	 * 过滤Map元素
	 *
	 * @param map		Map
	 * @param condition	过滤条件
	 *
	 * @author 延晓磊
	 *
	 * @since 2020年7月28日
	 */
	public static <K,V>Map<K,V> filter(Map<K,V> map, Predicate<Entry<K,V>> condition) {
		if (map == null || map.isEmpty()) {
			return map;
		}
		// 遍历，过滤
		Map<K,V> newMap = new LinkedHashMap<>();
		for (Entry<K,V> entry : map.entrySet()) {
		    if (condition.test(entry)) {
		    	newMap.put(entry.getKey(), entry.getValue());
		    }
		}
		return newMap;
	}

	/**
	 * 过滤Map
	 *
	 * @param map
	 * @param filter	过滤名：‘’无，*全部，xx*模糊匹配，多个用,分隔
	 * @return
	 *
	 * @author 延晓磊
	 * @since 2020年10月10日
	 */
	public static Map<String, String> filter(Map<String, String> map, String filter){
		return filter(map, filter, null);
	}

	/**
	 * 过滤Map
	 *
	 * @param map
	 * @param filter	过滤名：‘’无，*全部，xx*模糊匹配，多个用,分隔
	 * @param noContainsHandler	指定名称不存在时的处理
	 * @return
	 *
	 * @author 延晓磊
	 * @since 2020年10月10日
	 */
	public static Map<String, String> filter(Map<String, String> map, String filter, Consumer<String> noContainsHandler){
		// 筛选
		if (MapUtils.isEmpty(map)) {
			return map;
		}
		if (StringUtils.isBlank(filter)) {
			return new HashMap<>();
		}
		if ("*".equals(filter)) {
			return map;
		} else {
			Map<String, String> ts = new LinkedHashMap<>();
			if (filter.endsWith("*")) {
				// *后缀匹配
				for (Entry<String, String> t : map.entrySet()) {
					if (AntUtil.ant(t.getKey(),filter)) {
						ts.put(t.getKey(), t.getValue());
					}
				}
			} else {
				// 单表 或 ,号分隔的多表
				String[] split = filter.split(",");
				for (String t : split) {
					if (map.containsKey(t)) {
						ts.put(t, ts.get(t));
					} else {
						if (noContainsHandler != null) {
							noContainsHandler.accept(t);
						}
					}
				}
			}
			return ts;
		}
	}

	/**
	 * 合并Map
	 *
	 * @param maps
	 * @return
	 *
	 * @author 延晓磊
	 * @since 2024年03月21日
	 */
	@SafeVarargs
	public static <K,V>Map<K,V> merge(Map<K,V> ... maps){
		if (ArrayUtils.isEmpty(maps)) {
			return null;
		}
		Map<K, V> result = null;
		for (Map<K, V> map : maps) {
		    if (map != null) {
		    	if (result == null) {
		    		result = map;
		    	}else{
		    		result.putAll(map);
				}
		    }
		}
		return result;
	}
}
